module ddr3_4port #(
    parameter 
            FRAME_ROW              = 16'd480,                                   // 一帧的行数
            FRAME_LINE             = 16'd640,                                   // 一帧的列数，16bit为一个单位
            WR0_BURST_LEN          = FRAME_LINE >> 2,                           // wr0_fifo一次突发要突发的长度，一个突发地址对应8个ddr地址，8x16bit
            WR1_BURST_LEN          = FRAME_LINE >> 2,                           // wr1_fifo一次突发要突发的长度
            RD0_BURST_LEN          = FRAME_LINE >> 2,                           // rd0_fifo一次突发要突发的长度
            RD1_BURST_LEN          = FRAME_LINE >> 2,                           // rd1_fifo一次突发要突发的长度
            WR0_THRESHOLD          = (FRAME_LINE >> 2) + (FRAME_LINE >> 3),     // wr0驱动ddr写的阈值——1.5行数据——单位 64bit
            WR0_THRESHOLD_BEGINE   = FRAME_LINE >> 2,
            WR1_THRESHOLD          = (FRAME_LINE >> 2) + (FRAME_LINE >> 3),     // wr1驱动ddr写的阈值——1.5行数据——单位 64bit
            WR1_THRESHOLD_BEGINE   = FRAME_LINE >> 2,
            RD0_THRESHOLD          = FRAME_LINE,                                // rd0驱动ddr写的阈值——1行数据——单位 16bit
            RD1_THRESHOLD          = FRAME_LINE >> 2,                           // rd1驱动ddr写的阈值——1行数据——单位 128bit
            RD1_BEGIN_ADDR         = FRAME_ROW*FRAME_LINE*2,                    // 614400~1228799
            WR1_BEGIN_ADDR         = FRAME_ROW*FRAME_LINE*2,                    // 614400~1228799
            GRAY_GET_FREAME_LIMITE = 16'd3                                      
)(
    input                   clk                 ,
    input                   rst_n               ,
    input                   sys_rst_n           ,
    input                   clk_200m            ,
    //ddr3---------------------------------------
    inout       [15:0]      ddr3_dq             ,
    inout       [ 1:0]      ddr3_dqs_n          ,
    inout       [ 1:0]      ddr3_dqs_p          ,
    output      [13:0]      ddr3_addr           ,
    output      [ 2:0]      ddr3_ba             ,
    output                  ddr3_ras_n          ,
    output                  ddr3_cas_n          ,
    output                  ddr3_we_n           ,
    output                  ddr3_reset_n        ,
    output                  ddr3_ck_p           ,
    output                  ddr3_ck_n           ,
    output                  ddr3_cke            ,
    output                  ddr3_cs_n           ,
    output      [ 1:0]      ddr3_dm             ,
    output                  ddr3_odt            ,
    output                  ddr3_init_done      ,
    output                  ddr3_ui_clk         ,
    //rd0----------------------------------------
    input                   rd0_rd_clk          ,
    input                   rd0_rd_en           ,
    output      [15:0]      rd0_16bit_dout      ,
    //wr0----------------------------------------
    input                   wr0_wr_clk          ,
    input       [ 7:0]      wr0_8bit_din        ,
    input                   wr0_wr_en           ,
    //rd1----------------------------------------
    input                   rd1_rd_clk          ,
    input                   rd1_rd_en           ,
    output     [127:0]      rd1_128bit_dout     ,
    //wr1----------------------------------------
    input                   wr1_wr_clk          ,
    input       [15:0]      wr1_16bit_din       ,
    input                   wr1_wr_en           
);

// ddr3 线网
wire             ui_clk                     ;
wire             init_calib_complete        ;
wire [ 24:0]     begin_addr                 ;
wire             rw                         ;
wire [  1:0]     mask_switch                ;
wire [127:0]     wr_data                    ;
wire [ 15:0]     burst_data_len             ;
wire             exc                        ;
wire             input_fifo_rd_en           ;
wire             output_fifo_wr_en          ;
wire [127:0]     rd_data                    ;
wire             rd_done                    ;
wire             wr_done                    ;

// rd0 线网
wire [10:0]      rd0_11bit_rd_cnt           ;
wire             rd0_output_fifo_wr_en      ;
wire [127:0]     rd0_rd_data                ;
wire             rd0_rd_done                ;
wire [ 24:0]     rd0_begin_addr             ;
wire             rd0_rw                     ;
wire [ 15:0]     rd0_burst_data_len         ;
wire             rd0_exc                    ;
wire             rd0_wr_clk                 ;

// wr0 线网
wire             wr0_rd_clk                 ;
wire [ 8:0]      wr0_9bit_rd_cnt            ;
wire             wr0_input_fifo_rd_en       ;
wire             wr0_wr_done                ;
wire [ 24:0]     wr0_begin_addr             ;
wire             wr0_rw                     ;
wire [  1:0]     wr0_mask_switch            ;
wire [127:0]     wr0_wr_data                ;
wire [ 15:0]     wr0_burst_data_len         ;
wire             wr0_exc                    ;
wire             wr0_first_frame_wr_done    ;

// wr1 线网
wire [  8:0]      wr1_9bit_rd_cnt           ;
wire [ 24:0]      wr1_begin_addr            ;
wire              wr1_rw                    ;
wire [  1:0]      wr1_mask_switch           ;
wire [127:0]      wr1_wr_data               ;
wire [ 15:0]      wr1_burst_data_len        ;
wire              wr1_exc                   ;
wire              wr1_input_fifo_rd_en      ;
wire              wr1_wr_done               ;
wire              wr1_first_frame_wr_done   ;

// rd1 线网
wire [  9:0]      rd1_9bit_rd_cnt           ;
wire [ 24:0]      rd1_begin_addr            ;
wire              rd1_rw                    ;
wire [ 15:0]      rd1_burst_data_len        ;
wire              rd1_exc                   ;
wire              rd1_output_fifo_wr_en     ;
wire [127:0]      rd1_rd_data               ;
wire              rd1_rd_done               ;

assign ddr3_ui_clk      = ui_clk;
assign rd0_wr_clk       = ui_clk;
assign rd1_wr_clk       = ui_clk;
assign wr1_rd_clk       = ui_clk;
assign wr0_rd_clk       = ui_clk;
assign ddr3_init_done   = init_calib_complete;

ddr3_rw u_ddr3_rw(
    .clk_200m           (clk_200m            ),
    .sys_rst_n          (sys_rst_n           ),
    .ddr3_dq            (ddr3_dq             ),
    .ddr3_dqs_n         (ddr3_dqs_n          ),
    .ddr3_dqs_p         (ddr3_dqs_p          ),
    .ddr3_addr          (ddr3_addr           ),
    .ddr3_ba            (ddr3_ba             ),
    .ddr3_ras_n         (ddr3_ras_n          ),
    .ddr3_cas_n         (ddr3_cas_n          ),
    .ddr3_we_n          (ddr3_we_n           ),
    .ddr3_reset_n       (ddr3_reset_n        ),
    .ddr3_ck_p          (ddr3_ck_p           ),
    .ddr3_ck_n          (ddr3_ck_n           ),
    .ddr3_cke           (ddr3_cke            ),
    .ddr3_cs_n          (ddr3_cs_n           ),
    .ddr3_dm            (ddr3_dm             ),
    .ddr3_odt           (ddr3_odt            ),
    .ui_clk             (ui_clk              ),
    .init_calib_complete(init_calib_complete ),
    .begin_addr         (begin_addr          ),
    .rw                 (rw                  ),
    .mask_switch        (mask_switch         ),
    .wr_data            (wr_data             ),
    .burst_data_len     (burst_data_len      ),
    .exc                (exc                 ),
    .input_fifo_rd_en   (input_fifo_rd_en    ),
    .output_fifo_wr_en  (output_fifo_wr_en   ),
    .rd_data            (rd_data             ),
    .rd_done            (rd_done             ),
    .wr_done            (wr_done             ) 
);

rd0 #(
    .FRAME_ROW      (FRAME_ROW    ),
    .FRAME_LINE     (FRAME_LINE   ),
    .RD0_BURST_LEN  (RD0_BURST_LEN),
    .RD0_THRESHOLD  (RD0_THRESHOLD)
) u_rd0(
    .clk                (ui_clk                 ),
    .rst_n              (rst_n                  ),
    .rd0_wr_clk         (rd0_wr_clk             ),
    .rd0_rd_clk         (rd0_rd_clk             ),
    .rd0_rd_en          (rd0_rd_en              ),
    .rd0_16bit_dout     (rd0_16bit_dout         ),
    .rd0_11bit_rd_cnt   (rd0_11bit_rd_cnt       ),
    .output_fifo_wr_en  (rd0_output_fifo_wr_en  ),
    .rd_data            (rd0_rd_data            ),
    .rd_done            (rd0_rd_done            ),
    .begin_addr         (rd0_begin_addr         ),
    .rw                 (rd0_rw                 ),
    .burst_data_len     (rd0_burst_data_len     ),
    .exc                (rd0_exc                )
);

wr0 #(
    .FRAME_ROW      (FRAME_ROW    ),
    .FRAME_LINE     (FRAME_LINE   ),
    .WR0_BURST_LEN  (WR0_BURST_LEN),
    .WR0_THRESHOLD  (WR0_THRESHOLD)
) u_wr0(
    .clk                    (ui_clk                 ),
    .rst_n                  (rst_n                  ),
    .wr0_wr_clk             (wr0_wr_clk             ),
    .wr0_rd_clk             (wr0_rd_clk             ),
    .wr0_8bit_din           (wr0_8bit_din           ),
    .wr0_wr_en              (wr0_wr_en              ),
    .wr0_9bit_rd_cnt        (wr0_9bit_rd_cnt        ),
    .input_fifo_rd_en       (wr0_input_fifo_rd_en   ),
    .wr_done                (wr0_wr_done            ),
    .begin_addr             (wr0_begin_addr         ),
    .rw                     (wr0_rw                 ),
    .mask_switch            (wr0_mask_switch        ),
    .wr_data                (wr0_wr_data            ),
    .burst_data_len         (wr0_burst_data_len     ),
    .exc                    (wr0_exc                ),
    .first_frame_wr_done    (wr0_first_frame_wr_done)
);

rd1 #(
    .FRAME_ROW      (FRAME_ROW     ),
    .FRAME_LINE     (FRAME_LINE    ),
    .RD1_BURST_LEN  (RD1_BURST_LEN ),
    .RD1_THRESHOLD  (RD1_THRESHOLD ),
    .RD1_BEGIN_ADDR (RD1_BEGIN_ADDR)
) u_rd1(
    .clk              (ui_clk               ),
    .rst_n            (rst_n                ),
    .rd1_wr_clk       (rd1_wr_clk           ),
    .rd1_rd_clk       (rd1_rd_clk           ),
    .rd1_rd_en        (rd1_rd_en            ),
    .rd1_128bit_dout  (rd1_128bit_dout      ),
    .rd1_9bit_rd_cnt  (rd1_9bit_rd_cnt      ),
    .output_fifo_wr_en(rd1_output_fifo_wr_en),
    .rd_data          (rd1_rd_data          ),
    .rd_done          (rd1_rd_done          ),
    .begin_addr       (rd1_begin_addr       ),
    .rw               (rd1_rw               ),
    .burst_data_len   (rd1_burst_data_len   ),
    .exc              (rd1_exc              )
);

wr1 #(
    .FRAME_ROW      (FRAME_ROW     ),
    .FRAME_LINE     (FRAME_LINE    ),
    .WR1_BURST_LEN  (WR1_BURST_LEN ),
    .WR1_THRESHOLD  (WR1_THRESHOLD ),
    .WR1_BEGIN_ADDR (WR1_BEGIN_ADDR),
    .GRAY_GET_FREAME_LIMITE (GRAY_GET_FREAME_LIMITE)
) u_wr1(
    .clk                    (ui_clk                 ),
    .rst_n                  (rst_n                  ),
    .wr1_wr_clk             (wr1_wr_clk             ),
    .wr1_rd_clk             (wr1_rd_clk             ),
    .wr1_16bit_din          (wr1_16bit_din          ),
    .wr1_wr_en              (wr1_wr_en              ),
    .wr1_9bit_rd_cnt        (wr1_9bit_rd_cnt        ),
    .input_fifo_rd_en       (wr1_input_fifo_rd_en   ),
    .wr_done                (wr1_wr_done            ),
    .begin_addr             (wr1_begin_addr         ),
    .rw                     (wr1_rw                 ),
    .mask_switch            (wr1_mask_switch        ),
    .wr_data                (wr1_wr_data            ),
    .burst_data_len         (wr1_burst_data_len     ),
    .exc                    (wr1_exc                ),
    .first_frame_wr_done    (wr1_first_frame_wr_done)
);

rw_arbitrate #(
    .WR0_THRESHOLD          (WR0_THRESHOLD       ),
    .WR0_THRESHOLD_BEGINE   (WR0_THRESHOLD_BEGINE),
    .WR1_THRESHOLD          (WR1_THRESHOLD       ),
    .WR1_THRESHOLD_BEGINE   (WR1_THRESHOLD_BEGINE),
    .RD0_THRESHOLD          (RD0_THRESHOLD       ),
    .RD1_THRESHOLD          (RD1_THRESHOLD       )
) u_rw_arbitrate(
    .clk                    (ui_clk                 ),
    .rst_n                  (sys_rst_n              ),
    .input_fifo_rd_en       (input_fifo_rd_en       ),
    .output_fifo_wr_en      (output_fifo_wr_en      ),
    .rd_data                (rd_data                ),
    .rd_done                (rd_done                ),
    .wr_done                (wr_done                ),
    .begin_addr             (begin_addr             ),
    .rw                     (rw                     ),
    .mask_switch            (mask_switch            ),
    .wr_data                (wr_data                ),
    .burst_data_len         (burst_data_len         ),
    .exc                    (exc                    ),
    .wr0_9bit_rd_cnt        (wr0_9bit_rd_cnt        ),
    .wr0_begin_addr         (wr0_begin_addr         ),
    .wr0_rw                 (wr0_rw                 ),
    .wr0_mask_switch        (wr0_mask_switch        ),
    .wr0_wr_data            (wr0_wr_data            ),
    .wr0_burst_data_len     (wr0_burst_data_len     ),
    .wr0_exc                (wr0_exc                ),
    .wr0_input_fifo_rd_en   (wr0_input_fifo_rd_en   ),
    .wr0_wr_done            (wr0_wr_done            ),
    .wr0_first_frame_wr_done(wr0_first_frame_wr_done),
    .rd0_11bit_rd_cnt       (rd0_11bit_rd_cnt       ),
    .rd0_begin_addr         (rd0_begin_addr         ),
    .rd0_rw                 (rd0_rw                 ),
    .rd0_burst_data_len     (rd0_burst_data_len     ),
    .rd0_exc                (rd0_exc                ),
    .rd0_output_fifo_wr_en  (rd0_output_fifo_wr_en  ),
    .rd0_rd_data            (rd0_rd_data            ),
    .rd0_rd_done            (rd0_rd_done            ),
    .wr1_9bit_rd_cnt        (wr1_9bit_rd_cnt        ),
    .wr1_begin_addr         (wr1_begin_addr         ),
    .wr1_rw                 (wr1_rw                 ),
    .wr1_mask_switch        (wr1_mask_switch        ),
    .wr1_wr_data            (wr1_wr_data            ),
    .wr1_burst_data_len     (wr1_burst_data_len     ),
    .wr1_exc                (wr1_exc                ),
    .wr1_input_fifo_rd_en   (wr1_input_fifo_rd_en   ),
    .wr1_wr_done            (wr1_wr_done            ),
    .wr1_first_frame_wr_done(wr1_first_frame_wr_done),
    .rd1_9bit_rd_cnt        (rd1_9bit_rd_cnt        ),
    .rd1_begin_addr         (rd1_begin_addr         ),
    .rd1_rw                 (rd1_rw                 ),
    .rd1_burst_data_len     (rd1_burst_data_len     ),
    .rd1_exc                (rd1_exc                ),
    .rd1_output_fifo_wr_en  (rd1_output_fifo_wr_en  ),
    .rd1_rd_data            (rd1_rd_data            ),
    .rd1_rd_done            (rd1_rd_done            )
);
endmodule